package com.baogu.factoryjob.job.handler;

import com.alibaba.druid.util.StringUtils;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.baogu.factoryjob.service.BaoGuDataService;
import com.baogu.factoryjob.service.SensordataService;
import com.baogu.factoryjob.service.TerminalCollectionService;
import com.baogu.factoryjob.service.remote.SensordataRemoteService;
import com.baogu.factoryjob.util.DateUtils;
import com.baogu.factoryjob.util.FastJsonUtils;
import com.baogu.factoryjob.util.UuidUtil;
import com.baogu.model.common.HttpResult;
import com.baogu.model.database.SensorData;
import com.baogu.model.database.SensorDataImport;
import com.baogu.model.database.where.SensorDataWhere;
import com.baogu.model.job.*;
import com.baogu.model.job.where.*;
import org.quartz.DisallowConcurrentExecution;
import org.quartz.Job;
import org.quartz.JobExecutionContext;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.math.BigDecimal;
import java.text.ParseException;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;

@Service @DisallowConcurrentExecution
public class SensordataJobHand implements Job {

    private final static int type = 3;

    @Override
    public void execute(JobExecutionContext jobExecutionContext) {
        System.out.println("开始执行定时任务！");
        HttpResult httpResult = sensordataRemoteService.getNewSensorData();
        if(httpResult == null || StringUtils.isEmpty(httpResult.getCode())){
            //远程调用为空
            System.out.println("远程调用为空");
            return;
        }
        JSONArray jsonObject = (JSONArray) httpResult.getData();
        List<JSONObject> impList = jsonObject.toJavaObject(List.class);
        if(impList.size()==0){
            //查询数据为空
            System.out.println("查询最新数据为空");
            return;
        }
        List<SensorData> allList = new ArrayList<>();
        for (JSONObject jsonObj:impList){
            SensorDataImport sd = jsonObj.toJavaObject(SensorDataImport.class);
            String version = sd.getVersion();
            String tableDate = DateUtils.format(sd.getLocalDatetime(),DateUtils.YYYYMM);
            if(StringUtils.isEmpty(tableDate)){
                continue;
            }
            HttpResult result = sensordataRemoteService.getSensorDataListByVsion(version,tableDate);
            if(httpResult == null || StringUtils.isEmpty(httpResult.getCode())){
                System.out.println("根据版本号："+version+" 查询数据为空");
                continue;
            }
            JSONArray arrayJson = (JSONArray) result.getData();
            List<JSONObject> sensorDataList = arrayJson.toJavaObject(List.class);
            saveSensorData(sensorDataList,allList,tableDate);
            sensordataRemoteService.completeImpSensorData(version);
        }
        System.out.println("数据抽取结束");
        for (SensorData sd:allList){
            String collectionPointId = baoGuDataService.isEffective(sd.getControllerId());
            if(StringUtils.isEmpty(collectionPointId)){
                //无效控制器
                saveErrorJob(FastJsonUtils.convertObjectToJSON(sd),"无效控制器",sd.getVersion());
                System.out.println("无效控制器");
                continue;
            }
            ControllersensorWhere where = new ControllersensorWhere();
            where.setPort(sd.getChannelId());
            where.setControllerId(sd.getControllerId());
            where.setAddrId(sd.getAddrId());
            Controllersensor controllersensor = baoGuDataService.getControllersensorByIdAndPort(where);
            if(controllersensor == null){
                //无关联信息
                saveErrorJob(FastJsonUtils.convertObjectToJSON(sd),"无关联信息",sd.getVersion());
                System.out.println(sd.getChannelId()+":"+sd.getControllerId()+":"+sd.getAddrId()+"无关联信息");
                continue;
            }
            try {
                updateLastTerminalCollectionData(sd,controllersensor,collectionPointId);
            } catch (ParseException e) {
                //时间格式转换异常
            }
        }
        System.out.println("数据计算完毕");
    }

    @Transactional
    public void reUploadData(ReUploadData reUploadData) throws ParseException {
        System.out.println("重新抽取数据开始");
        //Date plusDate = DateUtils.plusData(reUploadData.getEndTime(),1);
        TerminalCollectionWhere terminalCollection = new TerminalCollectionWhere();
        terminalCollection.setAddrId(reUploadData.getOldAddrId());
        terminalCollection.setPort(reUploadData.getOldPort());
        terminalCollection.setControllerId(reUploadData.getControllerId());
        terminalCollection.setBeginTime(reUploadData.getBeginTime());
        terminalCollection.setEndTime(reUploadData.getEndTime());
        //System.out.println("sendData==>" + DateUtils.format(reUploadData.getBeginTime(),DateUtils.DATE_TIME_PATTERN) + " || " + DateUtils.format(reUploadData.getEndTime(),DateUtils.DATE_TIME_PATTERN));
        //System.out.println((DateUtils.format(DateUtils.plusData(reUploadData.getEndTime(),1),DateUtils.DATE_TIME_PATTERN)));
        terminalCollectionService.del(terminalCollection);
        terminalCollectionService.delLast(terminalCollection);
        List<SensorData> allList = new ArrayList<>();
        List<String> dateList = DateUtils.getMonthBetween(reUploadData.getBeginTime(), reUploadData.getEndTime());
        for (String s:dateList){
            SensorDataWhere where = new SensorDataWhere();
            where.setBeginTime(reUploadData.getBeginTime());
            where.setEndTime(reUploadData.getEndTime());
            where.setControllerId(reUploadData.getControllerId());
            where.setChannelId(reUploadData.getOldPort());
            where.setAddrId(reUploadData.getOldAddrId());
            where.setTableDate(s);
            List<SensorData> list = sensordataService.getSensorDataList(where);
            if (list != null && list.size() > 0){
                allList.addAll(list);
            }
            //allList.addAll(list);
        }
        for (SensorData sd:allList){
            //sd.setControllerId(reUploadData.getControllerId());
            if(!StringUtils.isEmpty(reUploadData.getNewAddrId())){
                sd.setAddrId(reUploadData.getNewAddrId());
            }
            if(!StringUtils.isEmpty(reUploadData.getNewPort())){
                sd.setChannelId(reUploadData.getNewPort());
            }
        }
        executeReload(allList);
        //pt_terminal_collection
        //pt_terminal_collection_last
        System.out.println("重新抽取数据结束");
    }

    public void executeReload(List<SensorData> sensorDataList){
        for(SensorData sd:sensorDataList){
            try {
                String collectionPointId = baoGuDataService.isEffective(sd.getControllerId());
                if(StringUtils.isEmpty(collectionPointId)){
                    //无效控制器
                    saveErrorJob(FastJsonUtils.convertObjectToJSON(sd),"无效控制器",sd.getVersion());
                    System.out.println("无效控制器");
                    continue;
                }
                ControllersensorWhere where = new ControllersensorWhere();
                where.setPort(sd.getChannelId());
                where.setControllerId(sd.getControllerId());
                where.setAddrId(sd.getAddrId());
                Controllersensor controllersensor = baoGuDataService.getControllersensorByIdAndPort(where);
                if(controllersensor == null){
                    //无关联信息
                    saveErrorJob(FastJsonUtils.convertObjectToJSON(sd),"无关联信息",sd.getVersion());
                    System.out.println(sd.getChannelId()+":"+sd.getControllerId()+":"+sd.getAddrId()+"无关联信息");
                    continue;
                }
                try {
                    updateLastTerminalCollectionData(sd,controllersensor,collectionPointId);
                } catch (ParseException e) {
                    //时间格式转换异常
                }
            }catch (Exception ex){
                ex.printStackTrace();
                continue;
            }
        }
    }

    public void execute(List<ErrorJob> list){
        for (ErrorJob errorJob:list){
            try {
                SensorData sd = FastJsonUtils.toBean(errorJob.getData(),SensorData.class);
                if(sd == null){
                    continue;
                }
                String collectionPointId = baoGuDataService.isEffective(sd.getControllerId());
                if(StringUtils.isEmpty(collectionPointId)){
                    //无效控制器
                    System.out.println("无效控制器");
                    continue;
                }
                ControllersensorWhere where = new ControllersensorWhere();
                where.setPort(sd.getChannelId());
                where.setControllerId(sd.getControllerId());
                where.setAddrId(sd.getAddrId());
                Controllersensor controllersensor = baoGuDataService.getControllersensorByIdAndPort(where);
                if(controllersensor == null){
                    //无关联信息
                    System.out.println(sd.getChannelId()+":"+sd.getControllerId()+":"+sd.getAddrId()+"无关联信息");
                    continue;
                }
                try {
                    updateLastTerminalCollectionData(sd,controllersensor,collectionPointId);
                } catch (ParseException e) {
                    //时间格式转换异常
                }
            }catch (Exception ex){
                ex.printStackTrace();
                continue;
            }
            ErrorJobWhere errorJobWhere = new ErrorJobWhere();
            errorJobWhere.setId(errorJob.getId());
            errorJobWhere.setState(1);
            baoGuDataService.updateErrorJobState(errorJobWhere);
        }
    }

    /**
     * 设置告警数据
     */
    private void setValuewarn(String collectionPointId,BigDecimal value,SensorData sd,TerminalCollection terminalCollection){
        CollectionPointCropRelWhere where = new CollectionPointCropRelWhere();
        where.setCollectionPointId(collectionPointId);
        where.setPlantStatus("PLANTING");
        CollectionPointCropRel collectionPointCropRel = this.baoGuDataService.getCollectionPointCropRel(where);
        if(collectionPointCropRel == null){
            //获取中间表数据
            System.out.println(collectionPointId+"：collectionPointCropRel数据为空");
            return;
        }
        String plantNum = collectionPointCropRel.getPlantNum();
        try{
            if("SINGLE".equals(collectionPointCropRel.getHarvestType())){
                single(plantNum,value,sd,collectionPointId,terminalCollection);
            }
            if("MANY".equals(collectionPointCropRel.getHarvestType()) && collectionPointCropRel.getBaseCycle().equals("CYCLE")){
                many(plantNum,value,sd,collectionPointId,terminalCollection,collectionPointCropRel);
            }
        }catch (Exception ex){
            ex.printStackTrace();
            return;
        }

        return;
    }

    /**
     * 单收作物
     */
    private void single(String plantNum,BigDecimal value,SensorData sd,String collectionPointId,TerminalCollection terminalCollection) throws ParseException {
        CropUploadDataPeriodRecordWhere where = new CropUploadDataPeriodRecordWhere();
        where.setPlantNum(plantNum);
        saveWaring(value,sd,collectionPointId,terminalCollection,where);
    }


    /**
     * 多收作物
     */
    private void many(String plantNum,BigDecimal value,SensorData sd,String collectionPointId,TerminalCollection terminalCollection,CollectionPointCropRel collectionPointCropRel){
        CollectionPointCropRelWhere collectionPointCropRelWhere = new CollectionPointCropRelWhere();
        collectionPointCropRelWhere.setCollectionPointId(collectionPointId);
        collectionPointCropRelWhere.setBaseCycle("BASE");
        collectionPointCropRelWhere.setHarvestType("MANY");
        collectionPointCropRelWhere.setPlantNum(plantNum);
        CollectionPointCropRel collectionPointCropRel1 = this.baoGuDataService.getCollectionPointCropRel(collectionPointCropRelWhere);
        CropUploadDataPeriodRecordWhere cropUploadDataPeriodRecordWhere = new CropUploadDataPeriodRecordWhere();
        cropUploadDataPeriodRecordWhere.getPointList().add(collectionPointCropRel.getId());
        cropUploadDataPeriodRecordWhere.getPointList().add(collectionPointCropRel1.getId());
        saveWaring(value,sd,collectionPointId,terminalCollection,cropUploadDataPeriodRecordWhere);
    }

    private void saveWaring(BigDecimal value,SensorData sd,String collectionPointId,TerminalCollection terminalCollection,CropUploadDataPeriodRecordWhere where){
        List<CropUploadDataPeriodRecord> list = this.baoGuDataService.getCropUploadDataPeriodRecord(where);
        if(list == null || list.size() == 0){
            return;
        }
        for (CropUploadDataPeriodRecord cropUploadDataPeriodRecord:list){
            if(cropUploadDataPeriodRecord.getLifeCycleBeginTime() == null){
                continue;
            }
            if (cropUploadDataPeriodRecord.getNextLifeCycleBeginTime() == null){
                continue;
            }
            if(sd.getLocalDateTime().getTime() < cropUploadDataPeriodRecord.getLifeCycleBeginTime().getTime() ||
                    sd.getLocalDateTime().getTime() > cropUploadDataPeriodRecord.getNextLifeCycleBeginTime().getTime()){
                continue;
            }
            if(StringUtils.isEmpty(cropUploadDataPeriodRecord.getPeriodSubType())){
                continue;
            }
            LiftCycleEntityWhere liftCycleEntityWhere = new LiftCycleEntityWhere();
            liftCycleEntityWhere.setId(cropUploadDataPeriodRecord.getPeriodSubType());
            LiftCycleEntity liftCycleEntity = this.baoGuDataService.getLiftCycleEntity(liftCycleEntityWhere);
            if(liftCycleEntity == null){
                System.out.println("liftCycleEntity为空");
                continue;
            }
            LiftWarnEntityWhere liftWarnEntityWhere = new LiftWarnEntityWhere();
            liftWarnEntityWhere.setLiftCycleId(liftCycleEntity.getId());
            liftWarnEntityWhere.setPlantId(liftCycleEntity.getPlantId());
            liftWarnEntityWhere.setWarnType(terminalCollection.getClassifyId());
            LiftWarnEntity liftWarnEntity = this.baoGuDataService.getLiftWarnEntity(liftWarnEntityWhere);
            if(liftWarnEntity == null){
                System.out.println("liftWarnEntity为空");
                continue;
            }
            if(liftWarnEntity.getIsSendMsg() == 0){
                System.out.println("该分类不发送阀值告警信息");
                continue;
            }
            if((liftWarnEntity.getWarningUp().compareTo(value) == 1) || (liftWarnEntity.getWarningDown().compareTo(value) == -1)){
                MessageNoticeEntity messageNoticeEntity = new MessageNoticeEntity();
                messageNoticeEntity.setId(UuidUtil.get32UUID());
                messageNoticeEntity.setCreateName("system");
                messageNoticeEntity.setCreateBy("system");
                messageNoticeEntity.setCreateDate(DateUtils.now());
                messageNoticeEntity.setUpdateName("system");
                messageNoticeEntity.setUpdateBy("system");
                messageNoticeEntity.setUpdateDate(DateUtils.now());
                messageNoticeEntity.setDeleteFlag(0);
                messageNoticeEntity.setIsEnabled(0);
                messageNoticeEntity.setHasInputToSend(0);
                messageNoticeEntity.setTitle("传感器阀值告警");
                messageNoticeEntity.setContent("作物周期：" + liftCycleEntity.getLiftName() + ",采集分类类型：" + liftWarnEntity.getWarnTypeName() + ",数据采集值：" + value.toString()
                        + ",数据采集时间:" + DateUtils.format(sd.getLocalDateTime(), DateUtils.DATE_TIME_PATTERN) + ",作物预警范围：" + liftWarnEntity.getWarningUp().toString() + " ~ " + liftWarnEntity.getWarningDown().toString());
                messageNoticeEntity.setShortContent("告警控制器ID:"+sd.getControllerId());
                messageNoticeEntity.setNoticeType("SYSTEMT_AUTO_SEND");
                messageNoticeEntity.setCollectionPointId(collectionPointId);
                baoGuDataService.saveMessageNotice(messageNoticeEntity);
                System.out.println("已发送阀值告警信息");
            }
            continue;
        }
    }

    private Integer updateLastTerminalCollectionData(SensorData sd,Controllersensor controllersensor,String collectionPointId) throws ParseException {
        TerminalCollectionWhere where = new TerminalCollectionWhere();
//        where.setCollectionPointId(collectionPointId);
        where.setPort(controllersensor.getPort());
        where.setControllerId(controllersensor.getControllerId());
        where.setAddrId(controllersensor.getAddrId());
        TerminalCollection terminalCollection = terminalCollectionService.getNewTerminalCollectionData(where);
        Integer result = 0;
        if (terminalCollection == null){
            saveTerminalCollectionData(sd,controllersensor,collectionPointId,true,null);
            saveTerminalCollectionData(sd,controllersensor,collectionPointId,false,null);
            return 1;
        }
        if(terminalCollection != null && DateUtils.getTimeBeforeAccurate(terminalCollection.getStorageTime(),sd.getLocalDateTime())<0){
            saveTerminalCollectionData(sd,controllersensor,collectionPointId,true,terminalCollection);
        }
        saveTerminalCollectionData(sd,controllersensor,collectionPointId,false,null);
        try{
            result = 1;
        }catch (Exception ex){
            saveErrorJob(FastJsonUtils.convertObjectToJSON(sd),ex.getMessage(),sd.getVersion());
            ex.printStackTrace();
            result = -1;
        }
        return result;
    }

    private Integer saveTerminalCollectionData(SensorData sd,Controllersensor controllersensor,String collectionPointId,Boolean isSaveLast,TerminalCollection newTerminalCollectionData){
        BigDecimal coefficient = controllersensor.getDisplayCoefficient();
        Integer result = 0;
        if(coefficient == null){
            //无效系数
            System.out.println("无效系数");
            coefficient = BigDecimal.ZERO;
            result = -1;
        }
        String sdValue = sd.getSensorReading();
        if(StringUtils.isEmpty(sdValue)){
            //无读数
            System.out.println("无读数");
            sdValue = "0";
            result = -1;
        }
        String ZeroDrift = controllersensor.getSensorZeroDrift();
        if(StringUtils.isEmpty(ZeroDrift)){
            //无零飘值
            System.out.println("无零飘值");
            ZeroDrift = "0";
            result = -1;
        }
        String updateDate = DateUtils.format(sd.getLocalDateTime(),DateUtils.DATE_TIME_PATTERN);
        BigDecimal value = coefficient.multiply(new BigDecimal(sdValue)).subtract(new BigDecimal(ZeroDrift));
        TerminalCollection terminalCollection = new TerminalCollection();
        terminalCollection.setCollectionPointId(collectionPointId);
        terminalCollection.setAddrId(controllersensor.getAddrId());
        terminalCollection.setCollectionValue(value);
        terminalCollection.setClassifyId(controllersensor.getClassifyId());
        terminalCollection.setPort(controllersensor.getPort());
        terminalCollection.setSensorId(controllersensor.getSensorId());
        terminalCollection.setId(UuidUtil.get32UUID());
        terminalCollection.setDataUploadDate(updateDate.substring(0,10));
        terminalCollection.setDataUploadTime(updateDate.substring(0,19));
        terminalCollection.setControllerId(sd.getControllerId());
        terminalCollection.setCreateTime(DateUtils.now());
        terminalCollection.setUpdateTime(DateUtils.now());
        terminalCollection.setVersion(sd.getVersion());
        try{
            terminalCollection.setStorageTime(sd.getLocalDateTime());
            if(isSaveLast)
            {
                if(newTerminalCollectionData == null){
                    terminalCollectionService.saveLastTerminalCollection(terminalCollection);
                }
                else{
                    terminalCollection.setId(newTerminalCollectionData.getId());
                    terminalCollectionService.updateLastData(terminalCollection);
                }
            }
            else {
                terminalCollectionService.saveTerminalCollection(terminalCollection);
            }
            result = 1;
            if(isSaveLast){
                setValuewarn(collectionPointId,value,sd,terminalCollection);
            }
        }catch (Exception ex){
            ex.printStackTrace();
            result = -1;
        }
        return result;
    }

    private SaveResultData saveSensorData(List<JSONObject> list,List<SensorData> allList,String tableDate){
        SaveResultData saveResultData = new SaveResultData();
        for (JSONObject jsonObj :list){
            SensorDataWhere sd = new SensorDataWhere();
            try{
                sd = jsonObj.toJavaObject(SensorDataWhere.class);
                sd.setTableDate(tableDate);
                Integer result = sensordataService.saveData(sd);
                if(result>0){
                    allList.add(sd);
                    saveResultData.sussceCount++;
                }
                else{
                    saveResultData.failCount++;
                }
            }catch (Exception ex){
                ex.printStackTrace();
                saveErrorJob(FastJsonUtils.convertObjectToJSON(sd),ex.getMessage(),sd.getVersion());
                continue;
            }
        }
        return saveResultData;
    }

    private void saveErrorJob(String data,String msg,String version){
        ErrorJobWhere where = new ErrorJobWhere();
        where.setCreateDate(DateUtils.now());
        where.setUpdateDate(DateUtils.now());
        where.setMsg(msg);
        where.setType(type);
        where.setState(0);
        where.setVersion(version);
        where.setData(data);
        baoGuDataService.saveErrorJob(where);
    }

    @Autowired
    TerminalCollectionService terminalCollectionService;
    @Autowired
    BaoGuDataService baoGuDataService;
    @Autowired
    SensordataRemoteService sensordataRemoteService;
    @Autowired
    SensordataService sensordataService;

    private class SaveResultData{
        public Integer sussceCount = 0;
        public Integer failCount = 0;
    }
}
